/*
 * @Description  :
 * @Version      : 0.2
 * @Company      : V-Think Development Team
 * @Author       : KiraVerSace@yeah.net
 * @Date         : 2024-12-05 13:09:22
 */
#include <Arduino.h>
#include <RingBuf.h>

#include <xCode.h>


#define LED_BUILTIN_G  PC0

RingBuf<uint8_t, 200> phaseRingBuffer;

HardwareTimer phaseSampleTimer(TIM2);
HardwareTimer phaseDelayTimer(TIM3);

bool phaseOutputDelayFlag = false;

#define PHASE1_BIT_POSITION     0
#define PHASE2_BIT_POSITION     1
#define PHASE3_BIT_POSITION     2
#define PHASE_IN1               PA8  // 用于计算输入PWM的频率和占空比
#define PHASE_IN2               PC8
#define PHASE_IN3               PC9
#define PHASE_OUT1              PB0
#define PHASE_OUT2              PB1
#define PHASE_OUT3              PB2


HardwareTimer *pwmMeasureTimer;
uint32_t measureBaseClockFrequency = 0;
/* Measure PWM frequency and dutyCycle */
volatile float    frequencyMeasured = 0, dutyCycleMeasured = 0;
volatile uint32_t freqCount         = 0, lastFreqCount = 0;
volatile uint32_t dutyCycleCount    = 0;


/* Interrupt Service Routines */
void phaseSampleTimerCallback(void);
void phaseDelayTimerCallback(void);
void pwmTimerCaptureRisingCallback(void);
void pwmTimerCaptureFallingCallback(void);

void setup()
{
    pinMode(LED_BUILTIN_G, OUTPUT);
    pinMode(PHASE_IN1,  INPUT);
    pinMode(PHASE_IN2,  INPUT);
    pinMode(PHASE_IN3,  INPUT);
    pinMode(PHASE_OUT1, OUTPUT);
    pinMode(PHASE_OUT2, OUTPUT);
    pinMode(PHASE_OUT3, OUTPUT);

    phaseSampleTimer.setPrescaleFactor(72);
    phaseSampleTimer.setOverflow(100);
    phaseSampleTimer.attachInterrupt(phaseSampleTimerCallback);

    phaseDelayTimer.setPrescaleFactor(72);
    phaseDelayTimer.setOverflow(10000);
    phaseDelayTimer.attachInterrupt(phaseDelayTimerCallback);

    Serial.begin(115200);

    pwmMeasureTimer = new HardwareTimer(TIM1);
    pwmMeasureTimer->setMode(1, TIMER_INPUT_FREQ_DUTY_MEASUREMENT, PHASE_IN1);
    /**
     * @brief 如果pwmTimer溢出,则说明测量的频率太低,将频率和占空比的值清零
     *        为了降低可测量最小频率,可以增加预分频器,会牺牲精度
     */
    pwmMeasureTimer->setPrescaleFactor(144);
    pwmMeasureTimer->setOverflow(0x10000);
    pwmMeasureTimer->attachInterrupt(1, pwmTimerCaptureRisingCallback);
    pwmMeasureTimer->attachInterrupt(2, pwmTimerCaptureFallingCallback);

    pwmMeasureTimer->resume();

    measureBaseClockFrequency = pwmMeasureTimer->getTimerClkFreq() / pwmMeasureTimer->getPrescaleFactor();


    Serial.printf(">>System start... [%d]MHz\r\n", SystemCoreClock / 1000000);
    Serial.printf(">>InputCapture Timer=[TIM1] parameters: \r\nClockFrequency = [%.2f]MHz\r\nPrescaleFactor = [%d]\r\nMeasureBaseClockFrequency = [%.2f]KHz\r\n",
                    pwmMeasureTimer->getTimerClkFreq() / 1000000.0F,
                    pwmMeasureTimer->getPrescaleFactor(),
                    measureBaseClockFrequency / 1000.0F);
    Serial.println("----------------------------VThink Development Team--------------------------------");
    Serial.println(">>Start to measure PWM frequency and dutyCycle...");

    delay(1000);    // 等待系统稳定

    if ((frequencyMeasured >= 45 ) && (frequencyMeasured <= 55))
    {
        phaseDelayTimer.setOverflow(10000);
        Serial.println(">>Phase=[50]Hz, Delay=[10]ms");
    }
    else if ((frequencyMeasured > 55) && (frequencyMeasured <= 65))
    {
        phaseDelayTimer.setOverflow(8330);
        Serial.println(">>Phase=[60]Hz, Delay=[8.33]ms");
    }
    else
    {
        phaseDelayTimer.setOverflow(10000);
        Serial.println(">>Phase=[Unknow], Delay=[10]ms(default)");
    }

    phaseSampleTimer.resume();
    phaseDelayTimer.resume();
}

void loop()
{
    Serial.printf("Frequency = %.2f, DutyCycle = %.2f\r\n", frequencyMeasured, dutyCycleMeasured);
    Serial.printf("RingBuffer Size = %d\r\n", phaseRingBuffer.size());
    delay(1000);

    digitalWrite(LED_BUILTIN_G, !digitalRead(LED_BUILTIN_G));
}


void phaseSampleTimerCallback(void)
{
    uint8_t pushData = 0;

    bitWrite(pushData, PHASE1_BIT_POSITION, digitalRead(PHASE_IN1));
    bitWrite(pushData, PHASE2_BIT_POSITION, digitalRead(PHASE_IN2));
    bitWrite(pushData, PHASE3_BIT_POSITION, digitalRead(PHASE_IN3));

    phaseRingBuffer.push(pushData);

    if (phaseOutputDelayFlag == true)
    {
        uint8_t popData = 0;

        if (phaseRingBuffer.pop(popData))
        {
            digitalWrite(PHASE_OUT1, bitRead(popData, PHASE1_BIT_POSITION));
            digitalWrite(PHASE_OUT2, bitRead(popData, PHASE2_BIT_POSITION));
            digitalWrite(PHASE_OUT3, bitRead(popData, PHASE3_BIT_POSITION));
        }
    }
}

void phaseDelayTimerCallback(void)
{
    phaseDelayTimer.pause();
    phaseOutputDelayFlag = true;
}

void pwmTimerCaptureRisingCallback(void)
{
    freqCount = pwmMeasureTimer->getCaptureCompare(1)+1;

    /* Frequency computation */
    if (freqCount > lastFreqCount)
    {
        frequencyMeasured = (float)measureBaseClockFrequency / (freqCount - lastFreqCount);
        dutyCycleMeasured = (float)(dutyCycleCount * 100) / (freqCount - lastFreqCount);
    }
    else if (freqCount <= lastFreqCount) // 0x1000 溢出
    {
        frequencyMeasured = (float)measureBaseClockFrequency / (0x10000 + freqCount - lastFreqCount);
        dutyCycleMeasured = (float)(dutyCycleCount * 100) / (0x10000 + freqCount - lastFreqCount);
    }

    /* 由于加了光耦逻辑需要取反 */
    // dutyCycleMeasured = 100.0F - dutyCycleMeasured;  // 暂时取消光耦,变为正逻辑

    lastFreqCount = freqCount;
}

void pwmTimerCaptureFallingCallback(void)
{
    freqCount = pwmMeasureTimer->getCaptureCompare(2)+1;

    /* DutyCycle computation */
    if (freqCount > lastFreqCount)
    {
        dutyCycleCount = freqCount - lastFreqCount;
    }
    else if (freqCount <= lastFreqCount)
    {
        dutyCycleCount = 0x10000 + freqCount - lastFreqCount;
    }
}
